#import "itpAppDelegate.h"

@implementation itpAppDelegate

@synthesize window, eventView, eventInfoLabel, accLabel, progressX, progressY, progressZ, accelerometer;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  [self.window makeKeyAndVisible];
  
  [self.eventView.layer addSublayer:self.eventIndicator];
  
  ITPTapPressureGestureRecognizer *tapPressureGesture = [[ITPTapPressureGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapPressure:)];
  tapPressureGesture.delegate = self;
  [self.window addGestureRecognizer:tapPressureGesture];
  [tapPressureGesture release];
  
  [self resetPressureLevel];
  _velocityArray = [[NSMutableArray alloc] init];
  
  self.accelerometer = [UIAccelerometer sharedAccelerometer];
  self.accelerometer.updateInterval = .01;
  self.accelerometer.delegate = self;
  
  return YES;
}

- (CALayer *)eventIndicator {
  if(!_eventIndicator) {
    _eventIndicator = [[CAShapeLayer alloc] init];
    _eventIndicator.fillColor = [[UIColor orangeColor] CGColor];
    _eventIndicator.lineWidth = 0.f;
    _eventIndicator.opacity = 0.f;
    _eventIndicator.shouldRasterize = YES;
  }
  return _eventIndicator;
}

- (void)showEventIndicatorAtPoint:(CGPoint)point pressureLevel:(int)pressure {
  [self.eventIndicator removeAllAnimations];
  [CATransaction begin];
  [CATransaction setAnimationDuration:.4f];
  [CATransaction setDisableActions:YES];
  
  self.eventIndicator.position = point;
  CGRect indicatorBounds = CGRectMake(0.f, 0.f, 50.f + 10.f * pressure, 50.f + 10.f * pressure);
  _eventIndicator.bounds = indicatorBounds;
  CGMutablePathRef circle = CGPathCreateMutable();
  CGPathAddEllipseInRect(circle, NULL, indicatorBounds);
  _eventIndicator.path = circle;
  CGPathRelease(circle);
  
  CABasicAnimation *fade = [CABasicAnimation animationWithKeyPath:@"opacity"];
  fade.fromValue = [NSNumber numberWithFloat:1.f];
  [self.eventIndicator addAnimation:fade forKey:@"fade"];
  
  [CATransaction commit];
}

- (void)handleTapPressure:(ITPTapPressureGestureRecognizer *)recognizer {
  if(recognizer.state == UIGestureRecognizerStateBegan) {
    [self updatePressureLevel];
    CGPoint location = [recognizer locationInView:self.eventView];
    self.eventInfoLabel.text = [NSString stringWithFormat:@"Began: (%f, %f), %d", location.x, location.y, _pressureLevel];
    [self showEventIndicatorAtPoint:location pressureLevel:_pressureLevel];
  }
  if (recognizer.state == UIGestureRecognizerStateChanged) {
    CGPoint location = [recognizer locationInView:self.eventView];
    self.eventInfoLabel.text = [NSString stringWithFormat:@"Changed: (%f, %f), %d", location.x, location.y, _pressureLevel];
    [self showEventIndicatorAtPoint:location pressureLevel:_pressureLevel];

  }
  if (recognizer.state == UIGestureRecognizerStateRecognized) {
    self.eventInfoLabel.text = [NSString stringWithFormat:@"Recognized: %d", _pressureLevel];
    [self resetPressureLevel];
  }
}

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration {
  [self addAcceleration:acceleration];
  double velocity = pow(acceleration.x, 2) + pow(acceleration.y, 2) + pow(acceleration.z, 2);
  
  accLabel.text = [NSString stringWithFormat:@"X: %f, Y: %f, Z: %f, v: %f", acceleration.x, acceleration.y, acceleration.z, velocity];
  
  self.progressX.progress = ABS(acceleration.x);
  self.progressY.progress = ABS(acceleration.y);
  self.progressZ.progress = ABS(acceleration.z);
}

- (void)addAcceleration:(UIAcceleration *)acceleration {
  double velocity = pow(acceleration.x, 2) + pow(acceleration.y, 2) + pow(acceleration.z, 2);
  [_velocityArray addObject:[NSNumber numberWithDouble:velocity]];
  if ([_velocityArray count] >= 11) {
    [_velocityArray removeObjectAtIndex:0];
  }
}

- (void)updatePressureLevel {
  if ([_velocityArray count] >= 10) {
    for (NSNumber *v in _velocityArray) {
      double currentVelocity = [v doubleValue] - 1;
      if (currentVelocity > 0) {
        [self newPressureLevel:(int)(currentVelocity / [self pressureInterval]) + 1];
      }
    }
  }
}

- (void)newPressureLevel:(int)pLevel {
  if (pLevel > _pressureLevel) {
    _pressureLevel = pLevel;
  }
}

- (void)resetPressureLevel {
  _pressureLevel = 0;
}

- (float)pressureInterval {
  return 0.3;
}

- (void)dealloc
{
  [_velocityArray release];
  [_eventIndicator release];
  [self.window release];
  [self.eventInfoLabel release];
  [self.eventView release];
  [super dealloc];
}

@end
